From 808bfe0a98ac4cd2e11ea4eed82a66470121c19b Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Fri, 6 Feb 2015 10:13:11 +0100 Subject: [PATCH] settings: Provide a default style cascade per scale This guarantees we only create 1 extra style cascade in total for hidpi and not one per style context. Style cascades are now nested like this: GtkSettings root cascade (scale == 1) | +-- GtkSettings per scale cascade (for any scale, no custom providers) | +-- GtkStyleContext custom cascade (for any scale, custom providers) This requires a bunch of care when changing cascade-related properties inside GtkStyleContext, so that it ends up with a properly setup cascade, but I think I got those cases right. The only thing we don't do yet is reverting to a GtkSettings cascade when the last custom provider is removed from a custom cascade. --- gtk/gtksettings.c | 41 ++++++++++++++++++++++++------- gtk/gtksettingsprivate.h | 3 ++- gtk/gtkstylecontext.c | 52 ++++++++++++++++++++++++---------------- 3 files changed, 65 insertions(+), 31 deletions(-) diff --git a/gtk/gtksettings.c b/gtk/gtksettings.c index 6908675724..e509b3025c 100644 --- a/gtk/gtksettings.c +++ b/gtk/gtksettings.c @@ -121,7 +121,7 @@ struct _GtkSettingsPrivate GData *queued_settings; /* of type GtkSettingsValue* */ GtkSettingsPropertyValue *property_values; GdkScreen *screen; - GtkStyleCascade *style_cascade; + GSList *style_cascades; GtkCssProvider *theme_provider; GtkCssProvider *key_theme_provider; }; @@ -294,7 +294,7 @@ gtk_settings_init (GtkSettings *settings) g_datalist_init (&priv->queued_settings); object_list = g_slist_prepend (object_list, settings); - priv->style_cascade = _gtk_style_cascade_new (); + priv->style_cascades = g_slist_prepend (NULL, _gtk_style_cascade_new ()); priv->theme_provider = gtk_css_provider_new (); /* build up property array for all yet existing properties and queue @@ -1745,24 +1745,46 @@ gtk_settings_finalize (GObject *object) settings_update_provider (priv->screen, &priv->theme_provider, NULL); settings_update_provider (priv->screen, &priv->key_theme_provider, NULL); - g_clear_object (&priv->style_cascade); + g_slist_free_full (priv->style_cascades, g_object_unref); G_OBJECT_CLASS (gtk_settings_parent_class)->finalize (object); } GtkStyleCascade * -_gtk_settings_get_style_cascade (GtkSettings *settings) +_gtk_settings_get_style_cascade (GtkSettings *settings, + gint scale) { + GtkSettingsPrivate *priv = settings->priv; + GtkStyleCascade *new_cascade; + GSList *list; + g_return_val_if_fail (GTK_IS_SETTINGS (settings), NULL); - return settings->priv->style_cascade; + for (list = priv->style_cascades; list; list = list->next) + { + if (_gtk_style_cascade_get_scale (list->data) == scale) + return list->data; + } + + /* We are guaranteed to have the special cascade with scale == 1. + * It's created in gtk_settings_init() + */ + g_assert (scale != 1); + + new_cascade = _gtk_style_cascade_new (); + _gtk_style_cascade_set_parent (new_cascade, _gtk_settings_get_style_cascade (settings, 1)); + _gtk_style_cascade_set_scale (new_cascade, scale); + + priv->style_cascades = g_slist_prepend (priv->style_cascades, new_cascade); + + return new_cascade; } static void settings_init_style (GtkSettings *settings) { static GtkCssProvider *css_provider = NULL; - GtkSettingsPrivate *priv = settings->priv; + GtkStyleCascade *cascade; /* Add provider for user file */ if (G_UNLIKELY (!css_provider)) @@ -1782,15 +1804,16 @@ settings_init_style (GtkSettings *settings) g_free (css_path); } - _gtk_style_cascade_add_provider (priv->style_cascade, + cascade = _gtk_settings_get_style_cascade (settings, 1); + _gtk_style_cascade_add_provider (cascade, GTK_STYLE_PROVIDER (css_provider), GTK_STYLE_PROVIDER_PRIORITY_USER); - _gtk_style_cascade_add_provider (priv->style_cascade, + _gtk_style_cascade_add_provider (cascade, GTK_STYLE_PROVIDER (settings), GTK_STYLE_PROVIDER_PRIORITY_SETTINGS); - _gtk_style_cascade_add_provider (priv->style_cascade, + _gtk_style_cascade_add_provider (cascade, GTK_STYLE_PROVIDER (settings->priv->theme_provider), GTK_STYLE_PROVIDER_PRIORITY_SETTINGS); diff --git a/gtk/gtksettingsprivate.h b/gtk/gtksettingsprivate.h index 4ba07cd2b8..e14ec5fb89 100644 --- a/gtk/gtksettingsprivate.h +++ b/gtk/gtksettingsprivate.h @@ -38,7 +38,8 @@ gboolean _gtk_settings_parse_convert (GtkRcPropertyParse GParamSpec *pspec, GValue *dest_value); GdkScreen *_gtk_settings_get_screen (GtkSettings *settings); -GtkStyleCascade *_gtk_settings_get_style_cascade (GtkSettings *settings); +GtkStyleCascade *_gtk_settings_get_style_cascade (GtkSettings *settings, + gint scale); typedef enum { diff --git a/gtk/gtkstylecontext.c b/gtk/gtkstylecontext.c index a7f700a348..9b4798e678 100644 --- a/gtk/gtkstylecontext.c +++ b/gtk/gtkstylecontext.c @@ -423,7 +423,7 @@ gtk_style_context_init (GtkStyleContext *style_context) priv->property_cache = g_array_new (FALSE, FALSE, sizeof (PropertyValue)); gtk_style_context_set_cascade (style_context, - _gtk_settings_get_style_cascade (gtk_settings_get_for_screen (priv->screen))); + _gtk_settings_get_style_cascade (gtk_settings_get_for_screen (priv->screen), 1)); } static void @@ -703,11 +703,18 @@ create_query_path (GtkStyleContext *context, } static gboolean -may_use_global_parent_cache (GtkStyleContext *context) +gtk_style_context_has_custom_cascade (GtkStyleContext *context) { GtkStyleContextPrivate *priv = context->priv; + GtkSettings *settings = gtk_settings_get_for_screen (context->priv->screen); + + return priv->cascade != _gtk_settings_get_style_cascade (settings, _gtk_style_cascade_get_scale (priv->cascade)); +} - if (priv->cascade != _gtk_settings_get_style_cascade (gtk_settings_get_for_screen (priv->screen))) +static gboolean +may_use_global_parent_cache (GtkStyleContext *context) +{ + if (gtk_style_context_has_custom_cascade (context)) return FALSE; return TRUE; @@ -1036,12 +1043,14 @@ gtk_style_context_add_provider (GtkStyleContext *context, priv = context->priv; - if (priv->cascade == _gtk_settings_get_style_cascade (gtk_settings_get_for_screen (priv->screen))) + if (!gtk_style_context_has_custom_cascade (context)) { GtkStyleCascade *new_cascade; new_cascade = _gtk_style_cascade_new (); - _gtk_style_cascade_set_parent (new_cascade, priv->cascade); + _gtk_style_cascade_set_scale (new_cascade, _gtk_style_cascade_get_scale (priv->cascade)); + _gtk_style_cascade_set_parent (new_cascade, + _gtk_settings_get_style_cascade (gtk_settings_get_for_screen (priv->screen), 1)); _gtk_style_cascade_add_provider (new_cascade, provider, priority); gtk_style_context_set_cascade (context, new_cascade); g_object_unref (new_cascade); @@ -1072,7 +1081,7 @@ gtk_style_context_remove_provider (GtkStyleContext *context, priv = context->priv; - if (priv->cascade == _gtk_settings_get_style_cascade (gtk_settings_get_for_screen (priv->screen))) + if (!gtk_style_context_has_custom_cascade (context)) return; _gtk_style_cascade_remove_provider (priv->cascade, provider); @@ -1145,7 +1154,7 @@ gtk_style_context_add_provider_for_screen (GdkScreen *screen, g_return_if_fail (GTK_IS_STYLE_PROVIDER (provider)); g_return_if_fail (!GTK_IS_SETTINGS (provider) || _gtk_settings_get_screen (GTK_SETTINGS (provider)) == screen); - cascade = _gtk_settings_get_style_cascade (gtk_settings_get_for_screen (screen)); + cascade = _gtk_settings_get_style_cascade (gtk_settings_get_for_screen (screen), 1); _gtk_style_cascade_add_provider (cascade, provider, priority); } @@ -1168,7 +1177,7 @@ gtk_style_context_remove_provider_for_screen (GdkScreen *screen, g_return_if_fail (GTK_IS_STYLE_PROVIDER (provider)); g_return_if_fail (!GTK_IS_SETTINGS (provider)); - cascade = _gtk_settings_get_style_cascade (gtk_settings_get_for_screen (screen)); + cascade = _gtk_settings_get_style_cascade (gtk_settings_get_for_screen (screen), 1); _gtk_style_cascade_remove_provider (cascade, provider); } @@ -1440,17 +1449,18 @@ gtk_style_context_set_scale (GtkStyleContext *context, if (scale == _gtk_style_cascade_get_scale (priv->cascade)) return; - if (priv->cascade == _gtk_settings_get_style_cascade (gtk_settings_get_for_screen (priv->screen))) + if (gtk_style_context_has_custom_cascade (context)) + { + _gtk_style_cascade_set_scale (priv->cascade, scale); + } + else { GtkStyleCascade *new_cascade; - - new_cascade = _gtk_style_cascade_new (); - _gtk_style_cascade_set_parent (new_cascade, priv->cascade); + + new_cascade = _gtk_settings_get_style_cascade (gtk_settings_get_for_screen (priv->screen), + scale); gtk_style_context_set_cascade (context, new_cascade); - g_object_unref (new_cascade); } - - _gtk_style_cascade_set_scale (priv->cascade, scale); } /** @@ -2368,7 +2378,6 @@ gtk_style_context_set_screen (GtkStyleContext *context, { GtkStyleContextPrivate *priv; GtkStyleCascade *screen_cascade; - GtkStyleCascade *old_screen_cascade; g_return_if_fail (GTK_IS_STYLE_CONTEXT (context)); g_return_if_fail (GDK_IS_SCREEN (screen)); @@ -2377,15 +2386,16 @@ gtk_style_context_set_screen (GtkStyleContext *context, if (priv->screen == screen) return; - screen_cascade = _gtk_settings_get_style_cascade (gtk_settings_get_for_screen (screen)); - old_screen_cascade = _gtk_settings_get_style_cascade (gtk_settings_get_for_screen (priv->screen)); - if (priv->cascade == old_screen_cascade) + if (gtk_style_context_has_custom_cascade (context)) { - gtk_style_context_set_cascade (context, screen_cascade); + screen_cascade = _gtk_settings_get_style_cascade (gtk_settings_get_for_screen (screen), 1); + _gtk_style_cascade_set_parent (priv->cascade, screen_cascade); } else { - _gtk_style_cascade_set_parent (priv->cascade, screen_cascade); + screen_cascade = _gtk_settings_get_style_cascade (gtk_settings_get_for_screen (screen), + _gtk_style_cascade_get_scale (priv->cascade)); + gtk_style_context_set_cascade (context, screen_cascade); } priv->screen = screen; -- 2.30.2